package org.kl.bpm.web.conf;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.kl.bf.entity.basic.CodeValues;
import org.kl.bf.entity.easyui.ComboBox;
import org.kl.bf.entity.easyui.EasyuiGrid;
import org.kl.bf.service.basic.CodeValuesService;
import org.kl.bf.utils.KLServlets;
import org.kl.bf.web.base.BasicController;
import org.kl.bpm.entity.conf.BpmConfBase;
import org.kl.bpm.entity.conf.BpmConfForm;
import org.kl.bpm.entity.conf.BpmConfNode;
import org.kl.bpm.entity.conf.BpmConfOperation;
import org.kl.bpm.entity.conf.BpmConfUser;
import org.kl.bpm.entity.conf.BpmProcess;
import org.kl.bpm.service.conf.BpmConfBaseService;
import org.kl.bpm.service.conf.BpmConfFormService;
import org.kl.bpm.service.conf.BpmConfNodeService;
import org.kl.bpm.service.conf.BpmConfOperationService;
import org.kl.bpm.service.conf.BpmConfUserService;
import org.kl.bpm.service.conf.BpmProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springside.modules.mapper.BeanMapper;
import org.springside.modules.utils.Collections3;
import org.springside.modules.web.MediaTypes;
import org.springside.modules.web.Servlets;

/**
 * 自己维护的流程定义
 * 
 * @Author hqm
 * @CreateTime 2014-3-13 下午9:34:36
 */
@Controller
@RequestMapping(value = "/bpm/process")
public class BpmProcessController extends BasicController {
	@Autowired
	private BpmProcessService bpmProcessService;
	@Autowired
	private BpmConfBaseService bpmConfBaseService;
	@Autowired
	private CodeValuesService codeValuesService;
	@Autowired
	private BpmConfNodeService bpmConfNodeService;
	@Autowired
	private BpmConfUserService bpmConfUserService;
	@Autowired
	private BpmConfFormService bpmConfFormService;
	@Autowired
	private BpmConfOperationService bpmConfOperationService;

	@RequiresPermissions("bpmProcess:list")
	@RequestMapping(method = RequestMethod.GET)
	public String list() {
		return "bpm/bpmProcessList";
	}

	@RequiresPermissions("bpmProcess:list")
	@RequestMapping(value = "dataGrid", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String dataGrid(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "rows", defaultValue = PAGE_SIZE) int pageSize,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request) {
		Map<String, Object> searchParams = KLServlets.getParametersStartingWith(request, SEARCH_PREFIX);
		Page<BpmProcess> bpmProcesss = bpmProcessService.getUserBpmProcess(searchParams, pageNumber, pageSize, sortType, orderType);
		EasyuiGrid grid = new EasyuiGrid();
		grid.setRows(bpmProcesss.getContent());
		grid.setTotal((int) bpmProcesss.getTotalElements());
		String result = jsonMapper.toJson(grid);
		return result;
	}

	/**
	 * 获取常用流程便于首页Portal显示
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "commonProcess", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String listCommonProcess(ServletRequest request) {
		List<BpmProcess> bpmProcesssList = bpmProcessService.findByBpmCategoryId("2c9689d0463af66d01463b2956c00011");
		String result = jsonMapper.toJson(bpmProcesssList);
		return result;
	}

	@RequiresPermissions("bpmProcess:export")
	@RequestMapping(value = "excelExport", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String excelExport(@RequestParam(value = "pageNumber", defaultValue = "1") int pageNumber,
			@RequestParam(value = "sort", defaultValue = "id") String sortType,
			@RequestParam(value = "order", defaultValue = "desc") String orderType, Model model, ServletRequest request,
			HttpServletResponse response) {
		Map<String, Object> searchParams = Servlets.getParametersStartingWith(request, SEARCH_PREFIX);
		List<BpmProcess> bpmProcesss = bpmProcessService.getAllUserBpmProcess(searchParams,sortType, orderType);
		super.export(BpmProcess.class, response, bpmProcesss, "流程配置");
		return null;
	}

	/**
	 * 流程定义下拉菜单
	 */
	@RequestMapping(value = "pdCombobox", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String pdCombobox() {
		List<BpmConfBase> bpmConfBaseList = bpmConfBaseService.getAllBpmConfBase();
		if (Collections3.isEmpty(bpmConfBaseList)) {
			return "{}";
		}
		List<ComboBox> combobox = new ArrayList<ComboBox>();
		for (BpmConfBase bcb : bpmConfBaseList) {
			ComboBox one = new ComboBox();
			one.setId(bcb.getId());
			one.setText(bcb.getProcessDefinitionId());
			one.setValue(bcb.getId());
			combobox.add(one);
		}
		return jsonMapper.toJson(combobox);
	}

	/**
	 * 流程信息下拉菜单
	 */
	@RequestMapping(value = "bpmProcessCombobox", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String bpmProcessCombobox() {
		List<BpmProcess> bpmProcessList = bpmProcessService.getAllBpmProcess();
		if (Collections3.isEmpty(bpmProcessList)) {
			return "{}";
		}
		List<ComboBox> combobox = new ArrayList<ComboBox>();
		for (BpmProcess bp : bpmProcessList) {
			ComboBox one = new ComboBox();
			one.setId(bp.getId());
			one.setText(bp.getName() + "[" + bp.getBpmConfBase().getProcessDefinitionId() + "]");
			one.setValue(bp.getId());
			combobox.add(one);
		}
		return jsonMapper.toJson(combobox);
	}

	@RequiresPermissions("bpmProcess:update")
	@RequestMapping(value = "update", method = RequestMethod.POST)
	@ResponseBody
	public String update(@Valid @ModelAttribute("bpmProcess") BpmProcess bpmProcess,
			@RequestParam(value = "bpmCategoryId", defaultValue = "-1") String bpmCategoryId,
			@RequestParam(value = "bpmConfBaseId", defaultValue = "-1") String bpmConfBaseId, RedirectAttributes redirectAttributes) {
		if (StringUtils.isNotBlank(bpmProcess.getId())) {
			BpmProcess old = bpmProcessService.getBpmProcess(bpmProcess.getId());
			if (old != null && !old.getBpmConfBase().getId().equals(bpmConfBaseId)) {
				bpmProcess.setLastConfBaseId(old.getBpmConfBase().getId());
			}
		}
		CodeValues cv = codeValuesService.getCodeValues(bpmCategoryId);
		bpmProcess.setBpmCategory(cv);
		BpmConfBase bcb = bpmConfBaseService.getBpmConfBase(bpmConfBaseId);
		bpmProcess.setBpmConfBase(bcb);
		bpmProcess.setCode(bcb.getProcessDefinitionKey());
		bpmProcessService.saveBpmProcess(bpmProcess);
		return ajaxMsg("编辑成功", true, null);
	}

	/**
	 * 将上一个流程定义中的用户配置拷贝到当前新的流程定义中
	 * 
	 * @param bpmProcessId
	 * @return
	 */
	@RequiresPermissions("bpmProcess:config")
	@RequestMapping(value = "updateConfUser", method = RequestMethod.GET)
	@ResponseBody
	public String updateConfUser(@RequestParam(value = "bpmProcessId", defaultValue = "-1") String bpmProcessId) {
		BpmProcess bpmProcess = bpmProcessService.getBpmProcess(bpmProcessId);
		if (bpmProcess == null) {
			return ajaxMsg("流程定义基础获取失败", false, null);
		}
		if (StringUtils.isBlank(bpmProcess.getLastConfBaseId())) {
			return ajaxMsg("流程定义基础上次流程定义ID没有获取到，不能更新", false, null);
		}
		List<BpmConfNode> bcnList = bpmConfNodeService.findByBpmConfBaseIdOrderByPriorityAsc(bpmProcess.getLastConfBaseId());
		for (BpmConfNode bcn : bcnList) {
			BpmConfNode thisBCN = bpmConfNodeService.findByCodeAndBpmConfBaseId(bcn.getCode(), bpmProcess.getBpmConfBase().getId());
			if (thisBCN != null) {
				bpmConfUserService.delete(new BpmConfUser(thisBCN));// 删除原有配置
				List<BpmConfUser> bcuList = bpmConfUserService.findByBpmConfNodeId(bcn.getId());
				for (BpmConfUser bcu : bcuList) {
					BpmConfUser one = BeanMapper.map(bcu, BpmConfUser.class);// 拷贝老配置
					one.setBpmConfNode(thisBCN);
					one.setId(null);
					bpmConfUserService.save(one);
				}
			}
		}
		return ajaxMsg("拷贝成功", true, null);
	}

	/**
	 * 将上一个流程定义中的操作配置拷贝到当前新的流程定义中
	 * 
	 * @param bpmProcessId
	 * @return
	 */
	@RequiresPermissions("bpmProcess:config")
	@RequestMapping(value = "updateConfOperation", method = RequestMethod.GET)
	@ResponseBody
	public String updateConfOperation(@RequestParam(value = "bpmProcessId", defaultValue = "-1") String bpmProcessId) {
		BpmProcess bpmProcess = bpmProcessService.getBpmProcess(bpmProcessId);
		if (bpmProcess == null) {
			return ajaxMsg("流程定义基础获取失败", false, null);
		}
		if (StringUtils.isBlank(bpmProcess.getLastConfBaseId())) {
			return ajaxMsg("流程定义基础上次流程定义ID没有获取到，不能更新", false, null);
		}
		List<BpmConfNode> bcnList = bpmConfNodeService.findByBpmConfBaseIdOrderByPriorityAsc(bpmProcess.getLastConfBaseId());
		for (BpmConfNode bcn : bcnList) {
			BpmConfNode thisBCN = bpmConfNodeService.findByCodeAndBpmConfBaseId(bcn.getCode(), bpmProcess.getBpmConfBase().getId());
			if (thisBCN != null) {
				bpmConfOperationService.delete(new BpmConfOperation(thisBCN));// 删除原有配置
				List<BpmConfOperation> bcuList = bpmConfOperationService.findByBpmConfNodeId(bcn.getId());
				for (BpmConfOperation bcu : bcuList) {
					BpmConfOperation one = BeanMapper.map(bcu, BpmConfOperation.class);
					one.setBpmConfNode(thisBCN);
					one.setId(null);
					bpmConfOperationService.saveBpmConfOperation(one);
				}
			}
		}
		return ajaxMsg("拷贝成功", true, null);
	}

	/**
	 * 将上一个流程定义中的表单配置拷贝到当前新的流程定义中
	 * 
	 * @param bpmProcessId
	 * @return
	 */
	@RequiresPermissions("bpmProcess:config")
	@RequestMapping(value = "updateConfForm", method = RequestMethod.GET)
	@ResponseBody
	public String updateConfForm(@RequestParam(value = "bpmProcessId", defaultValue = "-1") String bpmProcessId) {
		BpmProcess bpmProcess = bpmProcessService.getBpmProcess(bpmProcessId);
		if (bpmProcess == null) {
			return ajaxMsg("流程定义基础获取失败", false, null);
		}
		if (StringUtils.isBlank(bpmProcess.getLastConfBaseId())) {
			return ajaxMsg("流程定义基础上次流程定义ID没有获取到，不能更新", false, null);
		}
		List<BpmConfNode> bcnList = bpmConfNodeService.findByBpmConfBaseIdOrderByPriorityAsc(bpmProcess.getLastConfBaseId());
		for (BpmConfNode bcn : bcnList) {
			BpmConfNode thisBCN = bpmConfNodeService.findByCodeAndBpmConfBaseId(bcn.getCode(), bpmProcess.getBpmConfBase().getId());
			if (thisBCN != null) {
				bpmConfFormService.delete(new BpmConfForm(thisBCN));
				List<BpmConfForm> bcuList = bpmConfFormService.findByBpmConfNodeId(bcn.getId());
				for (BpmConfForm bcu : bcuList) {
					BpmConfForm one = BeanMapper.map(bcu, BpmConfForm.class);
					one.setBpmConfNode(thisBCN);
					one.setId(null);
					bpmConfFormService.save(one);
				}
			}
		}
		return ajaxMsg("拷贝成功", true, null);
	}

	@RequiresPermissions({ "bpmProcess:delete", "bpmProcess:update" })
	@RequestMapping(value = "delete/{id}", produces = MediaTypes.JAVASCRIPT_UTF_8)
	@ResponseBody
	public String delete(@PathVariable("id") String id, RedirectAttributes redirectAttributes) {
		bpmProcessService.deleteBpmProcess(id);
		return ajaxMsg("删除成功", true, null);
	}

	/**
	 * 所有RequestMapping方法调用前的Model准备方法, 实现Struts2
	 * Preparable二次部分绑定的效果,先根据form的id从数据库查出Task对象,再把Form提交的内容绑定到该对象上。
	 * 因为仅update()方法的form中有id属性，因此仅在update时实际执行.
	 */
	@ModelAttribute
	public void getBpmProcess(@RequestParam(value = "id", defaultValue = "-1") String id, Model model) {
		if (!id.equals("-1")) {
			model.addAttribute("bpmProcess", bpmProcessService.getBpmProcess(id));
		}
	}
}
